//==========================================================================
// Copyright (c) 2000-2009,  Elastos, Inc.  All Rights Reserved.
//==========================================================================
#ifndef __CGRAFIXSURFACE_H__
#define __CGRAFIXSURFACE_H__

#include <engine.h>

#define _NO_CGRAFIXSURFACE_CLASSOBJECT_
#include "_CGrafixSurface.h"

class CGrafixObject;

CarClass(CGrafixSurface)
{
public:
    CGrafixSurface()
    {
        m_parent = NULL;
        m_userRectangle = NULL;
        m_enable = FALSE;
        m_flipRectangle = NULL;
        m_flipRectangleRecord = NULL;
        m_directVisibleRectangle = NULL;
        m_directVisibleRectangleRecord = NULL;
        m_invalidRectangle = NULL;
        m_cacheBuffer = NULL;
        m_grafixObject = NULL;
        m_mapped = FALSE;

        FusionVectorInit(&m_subSurface, 4);
    }

    Void DisableSurface();

    ~CGrafixSurface();

    CARAPI Initialize(
        /* [in] */ GrafixSurfaceParams params,
        /* [in] */ CGrafixObject * pGrafixObject);

    Void *operator new(size_t size, Void* pv) { return pv; }

    Void *operator new(size_t size) { return malloc(size); }

    Void operator delete(Void* pv) { free(pv); }

public:
    CARAPI GetBufferInformation(
        /* [out] */ struct BitmapBufInfo * pBufferInfo);

    CARAPI EndBufferOperation();

    CARAPI GetPixelFormat(
        /* [out] */ PixelFormat * pFormat);

    CARAPI GetAttribute(
        /* [out] */ GrafixAttribute * pAttribute);

    CARAPI SetOffset(
        /* [in] */ Int32 deltaX,
        /* [in] */ Int32 deltaY);

    CARAPI SetBounds(
        /* [in] */ Int32 x,
        /* [in] */ Int32 y,
        /* [in] */ Int32 width,
        /* [in] */ Int32 height,
        /* [in] */ GrafixBound bound);

    CARAPI GetBounds(
        /* [out] */ Int32 * pX,
        /* [out] */ Int32 * pY,
        /* [out] */ Int32 * pWidth,
        /* [out] */ Int32 * pHeight);

    CARAPI SetClip(
        /* [in] */ Int32 x,
        /* [in] */ Int32 y,
        /* [in] */ Int32 width,
        /* [in] */ Int32 height);

    CARAPI GetClip(
        /* [out] */ Int32 * pX,
        /* [out] */ Int32 * pY,
        /* [out] */ Int32 * pWidth,
        /* [out] */ Int32 * pHeight);

    CARAPI GetVisibleRegion(
        /* [out] */ Int32 * pX,
        /* [out] */ Int32 * pY,
        /* [out] */ Int32 * pWidth,
        /* [out] */ Int32 * pHeight);

    CARAPI Blit(
        /* [in] */ IGrafixSurface * pSrcSurface,
        /* [in] */ Int32 srcX,
        /* [in] */ Int32 srcY,
        /* [in] */ Int32 width,
        /* [in] */ Int32 height,
        /* [in] */ Int32 dstX,
        /* [in] */ Int32 dstY)
    {
        return Blit(pSrcSurface, srcX, srcY, width, height, dstX, dstY, 0);
    }

    CARAPI BlitFromA8(
        /* [in] */ IGrafixSurface * pSrcSurface,
        /* [in] */ Int32 srcX,
        /* [in] */ Int32 srcY,
        /* [in] */ Int32 width,
        /* [in] */ Int32 height,
        /* [in] */ Int32 dstX,
        /* [in] */ Int32 dstY,
        /* [in] */ Color color)
    {
        assert(ColorRegular(color));
        return Blit(pSrcSurface, srcX, srcY, width, height, dstX, dstY, color);
    }

    CARAPI StretchBlit(
        /* [in] */ IGrafixSurface * pSrcSurface,
        /* [in] */ Int32 srcX,
        /* [in] */ Int32 srcY,
        /* [in] */ Int32 srcW,
        /* [in] */ Int32 srcH,
        /* [in] */ Int32 dstX,
        /* [in] */ Int32 dstY,
        /* [in] */ Int32 dstW,
        /* [in] */ Int32 dstH)
    {
        return StretchBlit(pSrcSurface, srcX, srcY, srcW, srcH,
                            dstX, dstY, dstW, dstH, 0);
    }

    CARAPI Flip(
        /* [in] */ Int32 x,
        /* [in] */ Int32 y,
        /* [in] */ Int32 width,
        /* [in] */ Int32 height);

    CARAPI GetSubGrafixSurface(
        /* [in] */ Int32 x,
        /* [in] */ Int32 y,
        /* [in] */ Int32 width,
        /* [in] */ Int32 height,
        /* [out] */ IGrafixSurface ** ppSubSurface);

    CARAPI InvalidateRectangle(
        /* [in] */ Int32 x,
        /* [in] */ Int32 y,
        /* [in] */ Int32 width,
        /* [in] */ Int32 height);

    CARAPI UpdateInvalidatedRectangles();

    CARAPI Clear(
        /* [in] */ Color color);

    CARAPI __Impl_GetBufferInformation(
        /* [out] */ struct BitmapBufInfo * pBufferInfo);

    CARAPI __Impl_ReGetBufferInformation(
        /* [out] */ struct BitmapBufInfo * pBufferInfo);

    CARAPI __Impl_EndBufferOperation();

public:
#ifdef _DEBUG
    Boolean CheckSurface() {
        if (!m_parent && m_cacheBuffer) {
            assert(m_format == m_cacheBuffer->m_buffer.info.pixelFormat);
            assert(!m_cacheBuffer->m_free);
            assert(m_attribute == m_cacheBuffer->m_buffer.attribute);
        }

        return TRUE;
    }
#endif

    ECode StretchBlit(
        /* [in] */ IGrafixSurface * pSrcSurface,
        /* [in] */ Int32 srcX,
        /* [in] */ Int32 srcY,
        /* [in] */ Int32 srcW,
        /* [in] */ Int32 srcH,
        /* [in] */ Int32 dstX,
        /* [in] */ Int32 dstY,
        /* [in] */ Int32 dstW,
        /* [in] */ Int32 dstH,
        /* [in] */ Color color);

    ECode StretchBlit(
        /* [in] */ CGrafixSurface * pSrcSurface,
        /* [in] */ Rectangle sourceRectangle,
        /* [in] */ Rectangle destinationRectangle,
        /* [in] */ Color color,
        /* [in] */ Boolean layerChannel = TRUE);

    ECode Blit(
        /* [in] */ IGrafixSurface * pSrcSurface,
        /* [in] */ Int32 srcX,
        /* [in] */ Int32 srcY,
        /* [in] */ Int32 width,
        /* [in] */ Int32 height,
        /* [in] */ Int32 dstX,
        /* [in] */ Int32 dstY,
        /* [in] */ Color color);

    ECode Blit(
        /* [in] */ CGrafixSurface * pSrcSurface,
        /* [in] */ Rectangle sourceRectangle,
        /* [in] */ Int32 dstX,
        /* [in] */ Int32 dstY,
        /* [in] */ Color color);

    Void ChangeSurfaceBuffer();

    CGrafixSurface * GetRoot();

public:
    Boolean m_enable;

    BufferCacheNode* m_cacheBuffer;
    GrafixAttribute m_attribute;
    PixelFormat m_format;

    Rectangle m_wantRectangle;  // relative coordinate
    Rectangle m_bornRectangle;  // absolute coordinate accroding to the buffer.
    Region m_clipRegion;        // absolute coordinate
    Rectangle* m_userRectangle;

    CGrafixObject* m_grafixObject;

    FusionVector m_subSurface;
    CGrafixSurface* m_parent;
    VinciLock m_lockSubSurface;

    RectangleLink* m_flipRectangle;
    RectangleLink* m_flipRectangleRecord;

    RectangleLink* m_directVisibleRectangle;
    RectangleLink* m_directVisibleRectangleRecord;

    RectangleLink* m_invalidRectangle;

    // for GetBufferInformation
    //
    Boolean m_mapped;
    Interlocked m_mapRef;
};

#endif // __CGRAFIXSURFACE_H__
